const Koa = require('koa')
const app = new Koa()
const views = require('koa-views')
const json = require('koa-json')
const onerror = require('koa-onerror')
const bodyparser = require('koa-bodyparser')
const logger = require('koa-logger')
const cors = require('koa-cors')
const jwt = require("jsonwebtoken");
const myKey = "2114i";
const session = require('koa-session');

//引入数据库
const db = require('./db')

const index = require('./routes/index')
const supermanage = require('./routes/supermanage')
const buy = require('./routes/buy')
const customer = require('./routes/customer')
const finance = require('./routes/finance')
const goods = require('./routes/goods')
const produce = require('./routes/produce')
const order = require('./routes/order')
const home = require('./routes/home')

app.keys = ['some secret hurr'];

const CONFIG = {
  key: 'koa.sess', /** (string) cookie key (default is koa.sess) */
  /** (number || 'session') maxAge in ms (default is 1 days) */
  /** 'session' will result in a cookie that expires when session/browser is closed */
  /** Warning: If a session cookie is stolen, this cookie will never expire */
  maxAge: 86400000,
  autoCommit: true, /** (boolean) automatically commit headers (default true) */
  overwrite: true, /** (boolean) can overwrite or not (default true) */
  httpOnly: true, /** (boolean) httpOnly or not (default true) */
  signed: true, /** (boolean) signed or not (default true) */
  rolling: false, /** (boolean) Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown. (default is false) */
  renew: false, /** (boolean) renew session when session is nearly expired, so we can always keep user logged in. (default is false)*/
  secure: false, /** (boolean) secure cookie*/
  sameSite: null, /** (string) session cookie sameSite options (default null, don't set it) */
};
// error handler
onerror(app)
// middlewares
app.use(session(CONFIG, app));
//允许跨域 允许跨域携带cookie
app.use(cors({
  // origin: "http://localhost:3000",
  credentials: true
}));

// middlewares
//对前端发来的请求进行数据解析
app.use(bodyparser({
  enableTypes: ['json', 'form', 'text']
}))
//返回json数据格式
app.use(json())

//token验证
app.use(async (ctx, next) => {
  let url = ctx.request.url;
  if (url == '/' || url == '/login' || url.indexOf('.jpg') != -1 || url.indexOf('.png') != -1)
    await next();
  else {
    let token = ctx.req.headers.authorization;
    if (token) {
      let err = await new Promise(resolve => {
        jwt.verify(token, myKey, function (err, payload) {
          if (!err) {
            ctx.payload = payload
          }
          resolve(err)
        })
      })
      if (err) {
        ctx.body = {
          msg: err.message === 'jwt expired' ? '用户登录过期,请重新登录' : '用户信息出错,请重新登录',
          err,
          status: 401
        }
        return
      }
      await next();
    } else {
      ctx.body = {
        msg: '用户未登录,请登录',
        status: 401
      }
      return
    }
  }
})

//权限验证中间件
app.use(async (ctx, next) => {
  let url = ctx.request.url;
  const urlarr = url.split("?");
  if (url == '/login' || url.indexOf('.jpg') != -1 || url.indexOf('.png') != -1 || url.indexOf('/supermanage/userlimits') != -1)
    await next();
  else {
    let admitRequest = ctx.req.headers.admitrequest;
    let admitArr = admitRequest.split(";");
    if (admitArr.includes(urlarr[0])) {
      await next()
    } else {
      ctx.body = {
        msg: '您没有当前操作权限',
        status: 403
      }
      return
    }
  }
})

app.use(logger())
app.use(require('koa-static')(__dirname + '/public'))

app.use(views(__dirname + '/views', {
  extension: 'ejs'
}))

// logger
app.use(async (ctx, next) => {
  const start = new Date()
  await next()
  const ms = new Date() - start
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`)
})

//db数据库
app.use(async (ctx, next) => {
  //后面所有路由处理时都可以访问到db数据库
  ctx.db = db
  await next()
})

// routes
app.use(index.routes(), index.allowedMethods())
app.use(supermanage.routes(), supermanage.allowedMethods())
app.use(buy.routes(), buy.allowedMethods())
app.use(customer.routes(), customer.allowedMethods())
app.use(finance.routes(), finance.allowedMethods())
app.use(goods.routes(), goods.allowedMethods())
app.use(produce.routes(), produce.allowedMethods())
app.use(order.routes(), order.allowedMethods())
app.use(home.routes(), home.allowedMethods())


// error-handling
app.on('error', (err, ctx) => {
  console.error('server error', err, ctx)
});

module.exports = app


//token验证流程
//1、客户端登录，发送用户信息给服务器，服务器验证用户信息成功后，生成一个token，返回给客户端
//2、客户端接收token，存储在本地，之后所有的请求都带上token
//3、客户端发送其他（非注册登录）的请求携带token
//4、服务器接收到请求后，验证token，这里是用jwt的规则对token进行解析，解析token是否过期，
//   解析token中用户的信息
//5、如果token仍在有效期内，并且通过服务器自定义的secret  key与加密方式，可以解析出用户信息，
//   服务器执行接收到的请求
